/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package algoritmo;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;


public class BidirectionalSearch extends DepthLimitedSearch {

    private List<Node> frontera, frontera2;
    private DepthLimitedSearch s2;
    private Node link1, link2;
    private int profMax;

    public BidirectionalSearch(int profMax) {
        super(1);
        this.profMax = profMax;
        s2 = new DepthLimitedSearch(1);
        frontera = new ArrayList<>();
        frontera2 = new ArrayList<>();

    }

    public Node search() {
        s2.setStart(goal);
        s2.setGoal(start);
        while (result == null) {
            super.search();
            s2.search();

            for (Node node : closed) {
                if (node.getDepth() == profDeCorte) {
                    frontera.add(node);
                }
            }
            
            for (Node node : s2.getClosed()) {
                if (node.getDepth() == s2.getProfDeCorte()) {
                    frontera2.add(node);
                }
            }
            
            

            if (link()) {
                buildCompleteResult();
                break;
            }
            
            profDeCorte++;
            s2.setProfDeCorte(s2.getProfDeCorte()+1);

            if (profDeCorte > profMax) {
                break;
            }
        }
        
        return result;
    } 

    public boolean link() {
        for (Node n2 : frontera2) {
            for (Node n1 : frontera) {
                if (n2.equals(n1)) {
                    link1 = n1;
                    link2 = n2;
                    return true;
                }
            }
        }
        
        return false;
    }

    public void buildCompleteResult() {
        
        Stack<Node> stack = new Stack<>();
        Node ap = link2;
        while (ap.hasPrev()) {
            ap = ap.prev();
            stack.push(ap);
        }
        ap = stack.pop();
        result = ap;
        while (!stack.isEmpty()) {
            ap.setPrev(stack.pop());
            ap = ap.prev();
        }
        ap.setPrev(link1);
    }
}
